package com.songlanyun.modules.payorder.controller.api;

import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bill99.crypto.service.CryptoService;
import com.bill99.crypto.service.processor.P7CryptoServiceProcessor;
import com.songlanyun.common.annotation.RepeatSubmit;
import com.songlanyun.common.enums.*;
import com.songlanyun.common.exception.RRException;
import com.songlanyun.common.kqUtils.QuickPayEnum;
import com.songlanyun.common.kqUtils.quick.Bill99CertConfigLoader;
import com.songlanyun.common.kqUtils.quick.Bill99ConfigInfo;
import com.songlanyun.common.supplychainapi.order.ApiOrderCommon;
import com.songlanyun.common.supplychainapi.order.model.Address;
import com.songlanyun.common.supplychainapi.order.model.CheckParam;
import com.songlanyun.common.supplychainapi.order.model.Spu;
import com.songlanyun.common.utils.OrderGen;
import com.songlanyun.common.utils.PageUtils;
import com.songlanyun.common.utils.R;
import com.songlanyun.common.utils.StrUtil;
import com.songlanyun.common.utils.custom.MathUtils;
import com.songlanyun.modules.account.controller.common.AbstractApiController;
import com.songlanyun.modules.account.service.UserThirdIdentityService;
import com.songlanyun.modules.exception.OrderException;
import com.songlanyun.modules.message.model.to.MessageTO;
import com.songlanyun.modules.message.service.SendPrivateMessageMsgService;
import com.songlanyun.modules.openSwitch.domain.YxtSwitch;
import com.songlanyun.modules.openSwitch.service.IYxtSwitchService;
import com.songlanyun.modules.order.entity.ChildOrder;
import com.songlanyun.modules.order.entity.Order;
import com.songlanyun.modules.order.entity.OrderReceipt;
import com.songlanyun.modules.order.model.vo.PayOrderDetailVo;
import com.songlanyun.modules.order.service.ChildOrderService;
import com.songlanyun.modules.order.service.OrderService;
import com.songlanyun.modules.payorder.entity.PayOrder;
import com.songlanyun.modules.payorder.model.dto.*;
import com.songlanyun.modules.payorder.service.PayOrderService;
import com.songlanyun.modules.payorder.service.SaleOrderReductionRecordService;
import com.songlanyun.modules.payrefund.entity.PayRefundOrder;
import com.songlanyun.modules.payrefund.service.PayRefundOrderService;
import com.songlanyun.modules.rabbitmq.mq.producer.SendOrderOrRightsOrderMsgService;
import com.songlanyun.modules.usercard.entity.UserCardEntity;
import com.songlanyun.modules.usercard.service.UserCardService;
import com.songlanyun.pay.common.api.ApiResult;
import com.songlanyun.pay.service.PayService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedWriter;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.*;

/**
 * 用来聚合支付的订单
 *
 * @author lubo
 * @email sunlightcs@gmail.com
 * @date 2020-11-17 09:16:34
 */
@RestController
@RequestMapping("api/pay/order")
@Slf4j
public class PayOrderApiController extends AbstractApiController {
    @Autowired
    private PayOrderService payOrderService;


    @Autowired
    private UserThirdIdentityService userThirdIdentityService;


    @Resource
    @Qualifier("payService2")
    private PayService payService;

    @Resource
    private OrderService orderService;

    @Resource
    private ChildOrderService childOrderService;

    @Resource
    private PayRefundOrderService payRefundOrderService;

    @Resource
    private SendOrderOrRightsOrderMsgService sendOrderOrRightsOrderMsgService;

    @Autowired
    private SendPrivateMessageMsgService sendPrivateMessageMsgService;

    @Autowired
    private ApiOrderCommon apiOrderCommon;

    @Autowired
    private UserCardService userCardService;

    @Autowired
    private IYxtSwitchService yxtSwitchService;

    @Autowired
    private SaleOrderReductionRecordService saleOrderReductionRecordService;



    /**
     * 会员分页查看待支付订单
     *
     * @param params
     * @return
     */
    @RequestMapping("/wait/page")
    public R waitPayPage(@RequestParam Map<String, Object> params) {
        params.put("user_id", getUserId(false));
        params.put("payment_status", 0);
        Integer orderType = MapUtil.getInt(params, "order_type");
        orderType = orderType == null ? 1 : 2;
        params.put("order_type", orderType);
        params.put("close", false);
        Integer areaFeature = MapUtil.getInt(params, "area_feature");
        areaFeature = areaFeature == null ? 0 : areaFeature;
        params.put("area_feature", areaFeature);
        params.put("client", getClient());
        PageUtils page = payOrderService.queryPage(params);
        return R.ok().put("page", page);
    }

    /**
     * 会员分页查看全部订单
     *
     * @param params
     * @return
     */
    @RequestMapping("/all/page")
    public R allPayPage(@RequestParam Map<String, Object> params) {
        params.put("user_id", getUserId(false));
        params.put("client", getClient());
        Integer orderType = MapUtil.getInt(params, "order_type");
        orderType = orderType == null ? 1 : orderType;
        params.put("order_type", orderType);

        Integer areaFeature = MapUtil.getInt(params, "area_feature");
        areaFeature = areaFeature == null ? 0 : areaFeature;
        params.put("area_feature", areaFeature);

        PageUtils page = payOrderService.queryPageAll(params);
        return R.ok().put("page", page);
    }

    /**
     * 支付订单的查询接口
     *
     * @param payOrderId
     * @return
     */
    @RequestMapping("/sale-detail/{payOrderId}")
    public R saleDetail(@PathVariable("payOrderId") Long payOrderId) {

        PayOrderDetailVo vo = payOrderService.getPayOrderSakeDetail(getUserId(true), payOrderId);
        return R.ok().put("page", vo);
    }


    /**
     * 支付订单的查询接口
     *
     * @param payOrderId
     * @return
     */
    @RequestMapping("/sale-detail-slim/{payOrderId}")
    public R saleDetailSlim(@PathVariable("payOrderId") Long payOrderId) {

        PayOrder payOrder = payOrderService.getByUserIdAndId(getUserId(true), payOrderId, true);
        return R.ok().put("data", payOrder);
    }

    /**
     * 所有订单支付入口(充值，普通销售订单，服务订单)
     *
     * @param dto
     * @return
     */
    @RepeatSubmit(value = "5")
    @PostMapping("/pay")
    @ResponseBody
    public R pay(@RequestBody PayOrderDTO dto) {

        Long userId = getUserId(true);
        //获取订单
        PayOrder payOrder = payOrderService.getByUserIdAndId(userId, dto.getPayOrderId(), true);
        validatePayOrder(payOrder);//校验订单

        BigDecimal totalAmount = payOrder.getTotalAmount();
        //如果是惠选订单可随机立减
        if(payOrder.getAreaFeature() == GoodsConstant.AreaFeature.ACTIVATING){
            Random random = new Random();
            // 生成一个1到5之间的随机整数
            int randomNumber = random.nextInt(5) + 1;
            // 将随机整数除以100得到0.01到0.05之间的随机数
            BigDecimal randomDecimal = BigDecimal.valueOf(randomNumber).divide(BigDecimal.valueOf(100));
            totalAmount = totalAmount.subtract(randomDecimal);
            //做记录
            saleOrderReductionRecordService.createSaleOrderReductionRecord(payOrder,randomDecimal,totalAmount);
        }
        BigDecimal totalPoint = payOrder.getTotalPoint();
        OrderConstant.PayMode byCode = OrderConstant.PayMode.getByCode(dto.getPayMode());
        OrderConstant.PayMode factPayMode = byCode;
        if (totalPoint.compareTo(BigDecimal.ZERO) > 0) {
            if (byCode.equals(OrderConstant.PayMode.WE_CHAT)) {
                factPayMode = OrderConstant.PayMode.WE_CHAT;
            } else if (byCode.equals(OrderConstant.PayMode.BALANCE)) {
                factPayMode = OrderConstant.PayMode.BALANCE;
            } else if (byCode.equals(OrderConstant.PayMode.ALIPAY_HUIFU)) {
                factPayMode = OrderConstant.PayMode.ALIPAY_HUIFU;
            } else if (byCode.equals(OrderConstant.PayMode.ALIPAY_HSQ)) {
                factPayMode = OrderConstant.PayMode.ALIPAY_HSQ;
            } else if (byCode.equals(OrderConstant.PayMode.KJ)) {
                factPayMode = OrderConstant.PayMode.KJ;
            } else {
                factPayMode = OrderConstant.PayMode.ALIPAY;
            }
        }

        payOrder.setPayMode(factPayMode);//支付方式
        String client = getClient();
        //支付渠道
        if (client.equals("applet")) {
            payOrder.setChannelType(OrderConstant.ChannelType.WE_APPLET);
        } else {
            payOrder.setChannelType(OrderConstant.ChannelType.APP);
        }
        payOrderService.modify(payOrder);
        YxtSwitch yxtSwitch = yxtSwitchService.selectYxtSwitchById(1L);
        ApiResult apiResult = null;
        if (OrderConstant.PayMode.WE_CHAT.equals(byCode)) {
            Integer thisSwitch = payOrder.getAreaFeature().getCode().equals(1) ? yxtSwitch.getHxWechatSwitch() : yxtSwitch.getShowWechatSwitch();
            //关闭微信支付
            if (thisSwitch == 0){
                throw new RRException("微信支付暂时关闭");
            }
            // 发起微信支付
            // 处理金额
            //获取openid
            client = getClient();
            if (client.equals("applet")) {
                String openId = userThirdIdentityService.getOpenIdByUserId(userId, true);
                apiResult = payOrderService.pay(payOrder.getCode(), totalAmount.toString(), openId, PayConstant.PayType.WECHAT_TRADE_APPLET_PAY.getCode());
            } else {
                //微信APP支付
                apiResult = payOrderService.pay(payOrder.getCode(), totalAmount.toString(), "", PayConstant.PayType.WECHAT_TRADE_APP_PAY.getCode(), OrderConstant.OrderType.REFILL_ORDER.equals(payOrder.getOrderType()) ? "转入" : "");
            }
        } else if (OrderConstant.PayMode.ALIPAY.equals(byCode)) {
//            Integer alipayPaymentSwitch = yxtSwitchService.selectYxtSwitchById(1L).getAlipayPaymentSwitch();
            Integer thisSwitch = payOrder.getAreaFeature().getCode().equals(1) ? yxtSwitch.getHxAlipaySwitch() : yxtSwitch.getShowAlipaySwitch();
            if (thisSwitch == 0){
                throw new RRException("支付宝支付暂时关闭");
            }
            apiResult = payOrderService.pay(payOrder.getCode(), totalAmount.toString(), "", PayConstant.PayType.ALIPAY_TRADE_APP_PAY.getCode(), OrderConstant.OrderType.REFILL_ORDER.equals(payOrder.getOrderType()) ? "转入" : "");
        } else if (OrderConstant.PayMode.ALIPAY_HUIFU.equals(byCode)) {
            List<Order> orders = payOrder.loadOrders();
            Order order = orders.get(0);
            List<ChildOrder> childOrderList = order.getChildOrderList(true);
            String goodsTitle = StrUtil.getNumStr(childOrderList.get(0).getGoodsTitle(), 50);
            String goodsDesc = StrUtil.getNumStr(childOrderList.get(0).getGoodsTitle(), 42);

            payOrder.setCode(OrderGen.generateOrderNo());
            payOrderService.modify(payOrder);
            orders.forEach(o -> {
                o.setPayOrderCode(payOrder.getCode());
                orderService.modify(o);
                List<ChildOrder> childOrderList1 = o.getChildOrderList(true);
                childOrderList1.forEach(c -> {
                    c.setPayOrderCode(payOrder.getCode());
                    childOrderService.modify(c);
                });
            });

            apiResult = payOrderService.pay(payOrder.getCode(), totalAmount.toString(), goodsTitle, goodsDesc, PayConstant.PayType.ORDER_PAY_TYPE_ALIPAY_HUIFU_APP.getCode(), OrderConstant.OrderType.REFILL_ORDER.equals(payOrder.getOrderType()) ? "转入" : "");
        }else if (OrderConstant.PayMode.KJ.equals(byCode)) {
            List<Order> orders = payOrder.loadOrders();
            Order order = orders.get(0);
            List<ChildOrder> childOrderList = order.getChildOrderList(true);
            String goodsTitle = StrUtil.getNumStr(childOrderList.get(0).getGoodsTitle(), 50);
            String goodsDesc = StrUtil.getNumStr(childOrderList.get(0).getGoodsTitle(), 42);

            payOrder.setCode(OrderGen.generateOrderNo());
            payOrderService.modify(payOrder);
            orders.forEach(o -> {
                o.setPayOrderCode(payOrder.getCode());
                orderService.modify(o);
                List<ChildOrder> childOrderList1 = o.getChildOrderList(true);
                childOrderList1.forEach(c -> {
                    c.setPayOrderCode(payOrder.getCode());
                    childOrderService.modify(c);
                });
            });
            UserCardEntity userCardEntity = userCardService.loadById(dto.getCardId(), true);
            apiResult = payOrderService.pay(payOrder.getCode(),userCardEntity.getTokenNo(), totalAmount.toString(), goodsTitle, goodsDesc, PayConstant.PayType.ORDER_PAY_TYPE_ADAPAY_KJ_APP.getCode(), OrderConstant.OrderType.REFILL_ORDER.equals(payOrder.getOrderType()) ? "转入" : "");
        } else if (OrderConstant.PayMode.ALIPAY_HSQ.equals(byCode)) {
            //重复提交时，更换订单号
            List<Order> orders = payOrder.loadOrders();
            payOrder.setCode(OrderGen.generateOrderNo());
            payOrderService.modify(payOrder);
            orders.forEach(o -> {
                o.setPayOrderCode(payOrder.getCode());
                orderService.modify(o);
                List<ChildOrder> childOrderList1 = o.getChildOrderList(true);
                childOrderList1.forEach(c -> {
                    c.setPayOrderCode(payOrder.getCode());
                    childOrderService.modify(c);
                });
            });
            apiResult = payOrderService.pay(payOrder.getCode(), totalAmount.toString(), PayConstant.PayType.ORDER_PAY_TYPE_ALIPAY_HSQ_MAIN.getCode(), payOrder.getOrderType().getMsg(), dto.getLongitude(), dto.getLatitude());
        } else if (OrderConstant.PayMode.QUICK_PAY_ALIPAY.equals(byCode)) {
            //重复提交时，更换订单号
            List<Order> orders = payOrder.loadOrders();
            Order order = orders.get(0);
            List<ChildOrder> childOrderList = order.getChildOrderList(true);
            String goodsDesc = StrUtil.getNumStr(childOrderList.get(0).getGoodsTitle(), 42);
//            payOrder.setCode(OrderGen.generateOrderNo());
//            payOrderService.modify(payOrder);
//            orders.forEach(o -> {
//                o.setPayOrderCode(payOrder.getCode());
//                orderService.modify(o);
//                List<ChildOrder> childOrderList1 = o.getChildOrderList(true);
//                childOrderList1.forEach(c -> {
//                    c.setPayOrderCode(payOrder.getCode());
//                    childOrderService.modify(c);
//                });
//            });
            apiResult = payOrderService.pay(payOrder.getCode(), totalAmount.toString(), PayConstant.PayType.QUICK_PAY_ALIPAY.getCode(), goodsDesc, dto.getLongitude(), dto.getLatitude());
        }  else if (OrderConstant.PayMode.QUICK_PAY_AWE_CHAT.equals(byCode)) {
            //重复提交时，更换订单号
            List<Order> orders = payOrder.loadOrders();
            Order order = orders.get(0);
            List<ChildOrder> childOrderList = order.getChildOrderList(true);
            String goodsDesc = StrUtil.getNumStr(childOrderList.get(0).getGoodsTitle(), 42);
//            payOrder.setCode(OrderGen.generateOrderNo());
//            payOrderService.modify(payOrder);
//            orders.forEach(o -> {
//                o.setPayOrderCode(payOrder.getCode());
//                orderService.modify(o);
//                List<ChildOrder> childOrderList1 = o.getChildOrderList(true);
//                childOrderList1.forEach(c -> {
//                    c.setPayOrderCode(payOrder.getCode());
//                    childOrderService.modify(c);
//                });
//            });
            apiResult = payOrderService.pay(payOrder.getCode(), totalAmount.toString(), PayConstant.PayType.QUICK_PAY_AWE_CHAT.getCode(), goodsDesc, dto.getLongitude(), dto.getLatitude());
        } else if (OrderConstant.PayMode.QUICK_PAY_BANK.equals(byCode)) {

            // 快钱快捷支付
            List<Order> orders = payOrder.loadOrders();
            Order order = orders.get(0);
            List<ChildOrder> childOrderList = order.getChildOrderList(true);
            String goodsDesc = StrUtil.getNumStr(childOrderList.get(0).getGoodsTitle(), 42);
            apiResult = payOrderService.pay(payOrder.getCode(), totalAmount.toString(), PayConstant.PayType.QUICK_PAY_BANK.getCode(), goodsDesc, dto.getLongitude(), dto.getLatitude(), dto.getValidCode());


        }else {
            Integer thisSwitch = payOrder.getAreaFeature().getCode().equals(1) ? yxtSwitch.getHxBalanceSwitch() : yxtSwitch.getShowBalanceSwitch();
            if (thisSwitch == 0){
                throw new RRException("余额支付暂时关闭");
            }
            apiResult = payOrderService.pay(payOrder.getCode(), totalAmount.toString(), "", PayConstant.PayType.BALANCE.getCode());
        }
        log.info("预支付数据:" + JSONObject.toJSONString(apiResult));
        return R.ok().put("data", apiResult).put("pay_order_id",payOrder.getId());
    }


    @RepeatSubmit(value = "5")
    @PostMapping("/kjPayConfirm")
    public R kjPayConfirm(@RequestBody AdaPayKJPayConfirmDTO dto){
        Map<String,Object> map = payOrderService.kjPayConfirm(dto);
        return R.ok().put("data", map);
    }

    @RepeatSubmit(value = "5")
    @PostMapping("/kjRepeatSendSms")
    public R payRepeatSendSms(@RequestBody AdaPayKJPayConfirmDTO dto){
        Map<String,Object> map = payOrderService.payRepeatSendSms(dto);
        return R.ok().put("data", map);
    }

    /**
     * 微信支付结果异步通知
     *
     * @param request 微信支付回调请求
     * @return
     */
    @RequestMapping(value = "/wxPayNotifyUrl", method = {RequestMethod.POST})
    @ResponseBody
    public String WXPayNotify(HttpServletRequest request) {
        String result = payService.wxPayNotify(request, (params) -> {
            Map<String, Object> par = (HashMap) params;
            String outTradeNo = par.get("out_trade_no").toString();//本地订单
            String transactionId = par.get("transaction_id").toString();//第三方单号(退款)
            String totalFee = par.get("total_fee").toString();//订单总金额，单位为分
            log.info("微信支付回调：{}", par);

            //微信返回的金额
            BigDecimal money = MathUtils.divide(new BigDecimal(totalFee), new BigDecimal("100"));
            try {
                PayOrder payOrder = payOrderService.paymentHandle(outTradeNo, transactionId, money, OrderConstant.PayMode.WE_CHAT);
                if (!payOrder.getOrderType().equals(OrderConstant.OrderType.REFILL_ORDER)) {
                    sendOrderOrRightsOrderMsgService.paySuccessSendMsg(payOrder);
                } else {
                    //发送充值商品支付成功站内消息
                    sendPrivateMessageMsgService.send(new MessageTO(PrivateMessageConstant.MessageType.PAY_MESSAGE,
                            PrivateMessageConstant.ModelType.REFILL_PAY_SUCCESS, payOrder.getId()));
                }
                return "success";
            } catch (RRException ex) {
                if (ex.getCode() == OrderException.NOT_REPEAT_PAY.getCode()) {
                    return "success";
                }
                return "fail";
            } catch (Exception ex) {
                return "fail";
            }

        });
        return result;
    }

    /**
     * 支付宝支付结果异步通知
     *
     * @param request 支付宝回调请求
     * @return
     */
    @RequestMapping(value = "/aliPayNotifyUrl", method = RequestMethod.POST)
    @ResponseBody
    public String aliPayNotify(HttpServletRequest request) {



        String result = payService.aliPayNotify(request, (params) -> {

            Map par = JSONObject.parseObject(JSONObject.toJSONString(params), Map.class);
            System.out.println("支付宝支付结果异步通知11111"+par);
            //param --- > 支付宝支付或退款 成功返回的 map
            if (par.get("isRefund").equals("1")) {
                String outRefundNo = par.get("out_biz_no").toString();//本地订单
                String refundId = par.get("trade_no").toString();//第三方单号(退款)
                String refundFee = par.get("refund_fee").toString();//订单总金额，单位为分
                BigDecimal money = MathUtils.divide(new BigDecimal(refundFee), new BigDecimal("100"));
                try {
                    PayRefundOrder payRefundOrder = payRefundOrderService.callbackHandle(outRefundNo, refundId, money, OrderConstant.PayMode.ALIPAY);
                    if (payRefundOrder != null && RightsOrderConstant.RightsRefundStatus.SUCCESS.equals(payRefundOrder.getRightsRefundStatus())) {
                        sendOrderOrRightsOrderMsgService.rightsRefundSuccessSendMsg(payRefundOrder);
                    }
                    return "success";
                } catch (RRException ex) {
                    if (ex.getCode() == OrderException.REPEAT_REFUND.getCode()) {
                        return "success";
                    }
                } catch (Exception ex) {
                    return "fail";
                }

                return "fail";   //会继续发消息
            } else {
                System.out.println("支付宝支付结果异步通知2222"+par);
                String tradeStatus = par.get("trade_status").toString();//交易状态
                String outTradeNo = par.get("out_trade_no").toString();//本地订单
                String transactionId = par.get("trade_no").toString();//第三方单号(退款)
                String totalFee = par.get("total_amount").toString();//订单总金额，单位为分
                String receiptAmountStr = String.valueOf(par.get("receipt_amount"));//实收金额。商家在交易中实际收到的款项，单位为人民币（元），精确到小数点后 2 位
                String buyerPayAmountStr = String.valueOf(par.get("buyer_pay_amount"));//用户在交易中支付的金额，单位为人民币（元），精确到小数点后 2 位
                //返回的金额
                BigDecimal money = new BigDecimal(totalFee);
                BigDecimal receiptAmount = new BigDecimal(receiptAmountStr);
                BigDecimal buyerPayAmount = new BigDecimal(buyerPayAmountStr);
                try {
                    //只有返回支付成功再继续,这是支付失败了
                    if (!tradeStatus.equals("TRADE_SUCCESS")){
                        Path path = Paths.get("/opt/gradelog/payfaillog.txt");//追加写模式
                        try (BufferedWriter writer =
                                     Files.newBufferedWriter(path,
                                             StandardCharsets.UTF_8,
                                             StandardOpenOption.APPEND)){
                            writer.write("本地订单号："+outTradeNo+"\n"
                                    +"支付宝交易号："+transactionId+"\n"
                                    +"支付宝交易金额："+totalFee+"\n"
                                    +"支付宝交易状态："+tradeStatus+"\n"
                                    +"时间："+new Date()+"\n"
                                    );
                        }catch (Exception e){

                        }
                        return "success";
                    }
                    //处理支付逻辑
                    Path path = Paths.get("/opt/gradelog/paysuccesslog.txt");//追加写模式
                    try (BufferedWriter writer =
                                 Files.newBufferedWriter(path,
                                         StandardCharsets.UTF_8,
                                         StandardOpenOption.APPEND)){
                        writer.write("本地订单号："+outTradeNo+"\n"
                                +"支付宝交易号："+transactionId+"\n"
                                +"支付宝交易金额："+totalFee+"\n"
                                +"支付宝交易状态："+tradeStatus+"\n"
                                +"时间："+new Date()+"\n"
                        );
                    }
                    PayOrder payOrder = payOrderService.paymentHandleForAliPay(outTradeNo, transactionId, receiptAmount, buyerPayAmount, OrderConstant.PayMode.ALIPAY);
                    //消费订单  支付成功发送消息
                    if (!payOrder.getOrderType().equals(OrderConstant.OrderType.REFILL_ORDER)) {
                        sendOrderOrRightsOrderMsgService.paySuccessSendMsg(payOrder);
                    } else {
                        //发送充值商品支付成功站内消息
                        sendPrivateMessageMsgService.send(new MessageTO(PrivateMessageConstant.MessageType.PAY_MESSAGE,
                                PrivateMessageConstant.ModelType.REFILL_PAY_SUCCESS, payOrder.getId()));
                    }
                    return "success";
                } catch (RRException ex) {
                    if (ex.getCode() == OrderException.NOT_REPEAT_PAY.getCode()) {
                        return "success";
                    }
                    return "fail";
                } catch (Exception ex) {
                    return "fail";
                }


            }
        });


        return result;
    }

    /**
     * 支付宝(汇付)支付结果异步通知
     *
     * @param request 支付宝回调请求
     * @return
     */
    @RequestMapping(value = "/adaPayNotifyUrl", method = RequestMethod.POST)
    @ResponseBody
    public String adaPayNotify(HttpServletRequest request) {

        String result = payService.adaPayNotify(request, (params) -> {

            Map par = JSONObject.parseObject(JSONObject.toJSONString(params), Map.class);
            String type = par.get("type").toString();
            String data = par.get("data").toString();
            switch (type) {
                case "payment.succeeded":
                    try {
                        Map dataMap = JSONObject.parseObject(data, Map.class);
                        String outTradeNo = dataMap.get("order_no").toString();
                        String money = dataMap.get("pay_amt").toString();
                        String transactionId = dataMap.get("id").toString();
                        //处理支付逻辑
                        PayOrder payOrder = payOrderService.paymentHandle(outTradeNo, transactionId, new BigDecimal(money), OrderConstant.PayMode.ALIPAY_HUIFU);
                        //消费订单  支付成功发送消息
                        if (!payOrder.getOrderType().equals(OrderConstant.OrderType.REFILL_ORDER)) {
                            sendOrderOrRightsOrderMsgService.paySuccessSendMsg(payOrder);
                        } else {
                            //发送充值商品支付成功站内消息
                            sendPrivateMessageMsgService.send(new MessageTO(PrivateMessageConstant.MessageType.PAY_MESSAGE,
                                    PrivateMessageConstant.ModelType.REFILL_PAY_SUCCESS, payOrder.getId()));
                        }
                        return "success";
                    } catch (RRException ex) {
                        if (ex.getCode() == OrderException.NOT_REPEAT_PAY.getCode()) {
                            return "success";
                        }
                        return "fail";
                    } catch (Exception ex) {
                        return "fail";
                    }
                case "payment.failed":
                    Map dataMap = JSONObject.parseObject(data, Map.class);
                    String outTradeNo = dataMap.get("order_no").toString();
                    String money = dataMap.get("pay_amt").toString();
                    String transactionId = dataMap.get("id").toString();
                    payOrderService.paymentFailHandle(outTradeNo, transactionId, new BigDecimal(money), OrderConstant.PayMode.ALIPAY_HUIFU);
                    return "success";
                case "refund.succeeded":
                    Map dataMap2 = JSONObject.parseObject(data, Map.class);
                    String refundOrderNo = dataMap2.get("refund_order_no").toString();
                    BigDecimal money2 = new BigDecimal(dataMap2.get("refund_amt").toString());
                    String refundId = dataMap2.get("id").toString();
                    PayRefundOrder refundOrder = payRefundOrderService.getByCode(refundOrderNo, true);
                    if (RightsOrderConstant.RightsRefundStatus.SUCCESS.equals(refundOrder.getRightsRefundStatus())) {
                        return "success";
                    }
                    payRefundOrderService.callbackHandle(refundOrderNo, refundId, money2, OrderConstant.PayMode.ALIPAY_HUIFU);
                    return "success";
                case "refund.failed":
                    Map dataMap3 = JSONObject.parseObject(data, Map.class);
                    String refundOrderNo3 = dataMap3.get("refund_order_no").toString();
                    BigDecimal money3 = new BigDecimal(dataMap3.get("refund_amt").toString());
                    String refundId3 = dataMap3.get("id").toString();
                    PayRefundOrder refundOrder3 = payRefundOrderService.getByCode(refundOrderNo3, true);
                    if (RightsOrderConstant.RightsRefundStatus.FAIL.equals(refundOrder3.getRightsRefundStatus())) {
                        return "success";
                    }
                    payRefundOrderService.callbackFailHandle(refundOrderNo3, refundId3, money3, OrderConstant.PayMode.ALIPAY_HUIFU);
                    return "success";
                default:
                    return "success";
            }

        });


        return result;
    }


    /**
     * 快捷支付结果异步通知
     *
     * @param request 支付宝回调请求
     * @return
     */
    @RequestMapping(value = "/adaKjPayNotifyUrl", method = RequestMethod.POST)
    @ResponseBody
    public String adaKjPayNotifyUrl(HttpServletRequest request) {

        String result = payService.adaPayNotify(request, (params) -> {

            Map par = JSONObject.parseObject(JSONObject.toJSONString(params), Map.class);
            String type = par.get("type").toString();
            String data = par.get("data").toString();

            switch (type) {
                case "fast_card.succeeded":
                    log.info("绑快捷卡成功："+data);
                    Map<String,Object> succeededMap = JSONObject.parseObject(data, Map.class);
                    String tokenNo = succeededMap.get("token_no").toString();
                    userCardService.setValidAndTokenNo(succeededMap.get("member_id").toString(),succeededMap.get("id").toString(),tokenNo);
                    return "success";
                case "fast_card.failed":
                    log.info("绑快捷卡失败："+data);
                    Map<String,Object> failedDataMap = JSONObject.parseObject(data, Map.class);
                    userCardService.setNoValidAndTokenNo(failedDataMap.get("member_id").toString(),failedDataMap.get("id").toString());
                    return "success";
                case "unbind_fast_card.succeeded":
                    log.info("解绑快捷卡成功："+data);
                    Map<String,Object> unbindSucceededMap = JSONObject.parseObject(data, Map.class);
                    userCardService.deleteByToKenNo(unbindSucceededMap.get("member_id").toString(),unbindSucceededMap.get("token_no").toString());
                    return "success";
                case "unbind_fast_card.failed":
                    log.info("解绑快捷卡失败："+data);
                    Map<String,Object> unbindFailedMap = JSONObject.parseObject(data, Map.class);
                    userCardService.setNoValidByTokenNo(unbindFailedMap.get("member_id").toString(),unbindFailedMap.get("token_no").toString());
                    return "success";
                case "payment.succeeded":
                    try {
                        log.info("快捷支付成功："+data);
                        Map dataMap = JSONObject.parseObject(data, Map.class);
                        String outTradeNo = dataMap.get("order_no").toString();
                        String money = dataMap.get("pay_amt").toString();
                        String transactionId = dataMap.get("id").toString();
                        //处理支付逻辑
                        PayOrder payOrder = payOrderService.paymentHandle(outTradeNo, transactionId, new BigDecimal(money), OrderConstant.PayMode.KJ);
                        //消费订单  支付成功发送消息
                        if (!payOrder.getOrderType().equals(OrderConstant.OrderType.REFILL_ORDER)) {
                            sendOrderOrRightsOrderMsgService.paySuccessSendMsg(payOrder);
                        } else {
                            //发送充值商品支付成功站内消息
                            sendPrivateMessageMsgService.send(new MessageTO(PrivateMessageConstant.MessageType.PAY_MESSAGE,
                                    PrivateMessageConstant.ModelType.REFILL_PAY_SUCCESS, payOrder.getId()));
                        }
                        return "success";
                    } catch (RRException ex) {
                        if (ex.getCode() == OrderException.NOT_REPEAT_PAY.getCode()) {
                            return "success";
                        }
                        return "fail";
                    } catch (Exception ex) {
                        return "fail";
                    }
                case "payment.failed":
                    log.info("快捷支付失败："+data);
                    Map dataMap = JSONObject.parseObject(data, Map.class);
                    String outTradeNo = dataMap.get("order_no").toString();
                    String money = dataMap.get("pay_amt").toString();
                    String transactionId = dataMap.get("id").toString();
                    payOrderService.paymentFailHandle(outTradeNo, transactionId, new BigDecimal(money), OrderConstant.PayMode.KJ);
                    return "success";
                case "refund.succeeded":
                    log.info("快捷支付退款成功："+data);
                    Map dataMap2 = JSONObject.parseObject(data, Map.class);
                    String refundOrderNo = dataMap2.get("refund_order_no").toString();
                    BigDecimal money2 = new BigDecimal(dataMap2.get("refund_amt").toString());
                    String refundId = dataMap2.get("id").toString();
                    PayRefundOrder refundOrder = payRefundOrderService.getByCode(refundOrderNo, true);
                    if (RightsOrderConstant.RightsRefundStatus.SUCCESS.equals(refundOrder.getRightsRefundStatus())) {
                        return "success";
                    }
                    payRefundOrderService.callbackHandle(refundOrderNo, refundId, money2, OrderConstant.PayMode.KJ);
                    return "success";
                case "refund.failed":
                    log.info("快捷支付退款失败："+data);
                    Map dataMap3 = JSONObject.parseObject(data, Map.class);
                    String refundOrderNo3 = dataMap3.get("refund_order_no").toString();
                    BigDecimal money3 = new BigDecimal(dataMap3.get("refund_amt").toString());
                    String refundId3 = dataMap3.get("id").toString();
                    PayRefundOrder refundOrder3 = payRefundOrderService.getByCode(refundOrderNo3, true);
                    if (RightsOrderConstant.RightsRefundStatus.FAIL.equals(refundOrder3.getRightsRefundStatus())) {
                        return "success";
                    }
                    payRefundOrderService.callbackFailHandle(refundOrderNo3, refundId3, money3, OrderConstant.PayMode.KJ);
                    return "success";
                default:
                    return "success";
            }

        });


        return result;
    }

    /**
     * 支付宝(慧支付)支付结果异步通知
     *
     * @param request 支付宝回调请求
     * @return
     */
    @RequestMapping(value = "/hsqPayNotifyUrl", method = RequestMethod.POST)
    @ResponseBody
    public String hsqPayNotifyUrl(HttpServletRequest request) {

        String result = payService.hsqPayNotify(request, (params) -> {
            Map par = JSONObject.parseObject(JSONObject.toJSONString(params), Map.class);
            String outTradeNo = par.get("transNo").toString();//本地订单
            String transactionId = par.get("tradeNo").toString();//第三方单号(退款)
            String totalFee = par.get("orderAmt").toString();//订单总金额，单位为分
            //返回的金额
            BigDecimal money = MathUtils.divide(new BigDecimal(totalFee), new BigDecimal("100"));
            String extend = par.get("extend").toString();
            String orderStatus = par.get("orderStatus").toString();
            switch (extend) {
                case "PAY":
                    if ("SUCCESS".equals(orderStatus)) {
                        try {
                            //处理支付逻辑
                            PayOrder payOrder = payOrderService.paymentHandle(outTradeNo, transactionId, money, OrderConstant.PayMode.ALIPAY_HSQ);
                            //消费订单  支付成功发送消息
                            if (!payOrder.getOrderType().equals(OrderConstant.OrderType.REFILL_ORDER)) {
                                sendOrderOrRightsOrderMsgService.paySuccessSendMsg(payOrder);
                            } else {
                                //发送充值商品支付成功站内消息
                                sendPrivateMessageMsgService.send(new MessageTO(PrivateMessageConstant.MessageType.PAY_MESSAGE,
                                        PrivateMessageConstant.ModelType.REFILL_PAY_SUCCESS, payOrder.getId()));
                            }
                            return "success";
                        } catch (RRException ex) {
                            if (ex.getCode() == OrderException.NOT_REPEAT_PAY.getCode()) {
                                return "success";
                            }
                            return "fail";
                        } catch (Exception ex) {
                            return "fail";
                        }
                    } else if ("FAIL".equals(orderStatus)) {
                        payOrderService.paymentFailHandle(outTradeNo, transactionId, money, OrderConstant.PayMode.ALIPAY_HSQ);
                        return "success";
                    } else {
                        return "success";
                    }
                case "REFUND":
                    PayRefundOrder refundOrder = payRefundOrderService.getByCode(outTradeNo, true);
                    if ("SUCCESS".equals(orderStatus)) {
                        if (RightsOrderConstant.RightsRefundStatus.SUCCESS.equals(refundOrder.getRightsRefundStatus())) {
                            return "success";
                        }
                        payRefundOrderService.callbackHandle(outTradeNo, transactionId, money, OrderConstant.PayMode.ALIPAY_HSQ);
                        return "success";
                    } else if ("FAIL".equals(orderStatus)) {
                        if (RightsOrderConstant.RightsRefundStatus.FAIL.equals(refundOrder.getRightsRefundStatus())) {
                            return "success";
                        }
                        payRefundOrderService.callbackFailHandle(outTradeNo, transactionId, money, OrderConstant.PayMode.ALIPAY_HSQ);
                        return "success";
                    } else {
                        return "success";
                    }
                default:
                    return "success";
            }
        });

        return result;
    }

    /**
     * 校验订单状态
     *
     * @param payOrder
     */
    private void validatePayOrder(PayOrder payOrder) {
        if (payOrder.getClose()) {
            //支付订单已关闭,不能取消支付
            throw new RRException(OrderException.PAY_ORDER_CLOSED_NOT_PAY);
        }

        if (payOrder.isFactPaySuccess()) {
            //支付订单已成功支付,不取消支付
            throw new RRException(OrderException.NOT_REPEAT_PAY);
        }

        if (payOrder.getExpiredPayTime() < System.currentTimeMillis()) {
            //支付已过期
            throw new RRException(OrderException.PAY_EXPIRED);
        }

        List<Order> orders = payOrder.loadOrders();
        for (Order order:orders) {
            if(!order.getThird())
            {
                continue;
            }
            OrderReceipt receipt = order.loadOrderReceipt();
            Address address = Address.builder()
                    .phone(receipt.getMobile())
                    .consignee(receipt.getReceiver())
                    .description(receipt.getAddress())
                    .province(receipt.getProvinceName())
                    .city(receipt.getCityName())
                    .area(receipt.getAreaName())
                    .street(" ")
                    .build();
            List<ChildOrder> childOrderList = order.getChildOrderList(true);
            Spu[] spuArr = childOrderList.stream().map(o -> {
                return Spu.builder().sku(o.getThirdSkuId()).number(o.getNumber()).build();
            }).toArray(Spu[]::new);
            CheckParam checkParam = CheckParam.builder().address(address).spu(spuArr)
                    .build();
//            apiOrderCommon.beforeCheck(checkParam);
        }

    }

    /**
     * 银行卡信息查询-通过卡号查询银行卡信息
     */
    @RequestMapping(value = "/getBankCardInfo", method = RequestMethod.POST)
    @ResponseBody
    public R getBankCardInfo(@RequestBody JSONObject req) throws Exception {
        return payOrderService.getCardInfo(req);
    }

    /**
     * 用户银行卡信息查询-查询本地数据库
     */
    @RequestMapping(value = "/getUserBankInfo", method = RequestMethod.POST)
    @ResponseBody
    public R getUserBankInfo(@RequestBody KqUserBankInfoReqDTO req) throws Exception {
        return payOrderService.getUserBankInfo(req);
    }

    /**
     * 首次绑定银行卡
     */
    @RequestMapping(value = "/firstBindingCard", method = RequestMethod.POST)
    @ResponseBody
    public R firstBindingCard(@RequestBody KqFirstCertificationReqDTO req) throws Exception {
        Long userId = getUserId(true);
        //获取订单
        PayOrder payOrder = payOrderService.getByUserIdAndId(userId, req.getPayOrderId(), true);

        req.setOrderNo(payOrder.getCode());
        // 元转分
        BigDecimal yuan2fen = payOrder.getTotalAmount().multiply(new BigDecimal(100)).setScale(0, RoundingMode.HALF_UP);
        req.setAmount(yuan2fen.toString());

        return payOrderService.firstBindingCard(req);
    }

    /**
     * 快捷支付申请
     */
    @RequestMapping(value = "/kqPayApply", method = RequestMethod.POST)
    @ResponseBody
    public R kqPayApply(@RequestBody KqPayApplyReqDTO req) throws Exception {
        Long userId = getUserId(true);
        //获取订单
        PayOrder payOrder = payOrderService.getByUserIdAndId(userId, req.getPayOrderId(), true);

        req.setOrderNo(payOrder.getCode());
        // 元转分
        BigDecimal yuan2fen = payOrder.getTotalAmount().multiply(new BigDecimal(100)).setScale(0, RoundingMode.HALF_UP);
        req.setAmount(yuan2fen.toString());

        return payOrderService.kqPayApply(req);
    }

    /**
     * 关闭验证码弹窗
     */
    @RequestMapping(value = "/closeVerify", method = RequestMethod.POST)
    @ResponseBody
    public R closeVerify(@RequestBody KqCloseVerifyReqDTO req) throws Exception {
        return payOrderService.closeVerify(req);
    }

    /**
     * 快钱快捷支付回调
     */
    @RequestMapping(value = "/quickBankPayNotifyUrl", method = RequestMethod.POST)
    @ResponseBody
    public JSONObject quickBankPayNotify(HttpServletRequest request, @RequestBody Map<String,Object> map) {
        log.info("快钱快捷支付回调: {}", map);
        log.info("快钱快捷支付回调: {}", request.getParameterNames());
        JSONObject notify = new JSONObject(map);

        log.info("快钱快捷支付回调JSON: {}", notify.toJSONString());

        JSONObject notifyBody = notify.getJSONObject("requestBody");
        JSONObject notifyHead = notify.getJSONObject("head");

        JSONObject notifyDecryptObject = new JSONObject();

        // 快钱订单直接返回成功
        JSONObject result = new JSONObject();
        JSONObject head = new JSONObject();
        JSONObject responseBody = new JSONObject();
        head.put("version", "1.0.0");
        head.put("messageType", "A9005");
        head.put("memberCode",  notifyHead.getString("memberCode"));
        head.put("externalRefNumber", notifyHead.getString("externalRefNumber"));
        responseBody.put("merchantId",notifyBody.getString("merchantId"));
        responseBody.put("refNumber",notifyBody.getString("refNumber"));
        responseBody.put("isReceived","1");
        result.put("head", head);
        result.put("responseBody", responseBody);

        // 回调解密
        try {
            String decryptData = null;
            String signedData = notifyBody.getString("signedData");
            String envelopedData = notifyBody.getString("envelopedData");
            CryptoService cryptoService = P7CryptoServiceProcessor.getInstance();
            cryptoService.setBill99CertConfig(Bill99CertConfigLoader.loadConfig());
            if(notifyBody.isEmpty()){
                throw new Exception("9bill notify body node is null!");
            }else{

                decryptData = cryptoService.unSeal(envelopedData,signedData);

                notifyDecryptObject.put("head",notifyHead);
                notifyDecryptObject.put("requestBody", JSON.parse(decryptData));
            }
        } catch ( Exception e) {
            log.error("快钱快捷支付回调报文解密异常：" + e.getMessage());
            return result;
        }

        JSONObject notifyDecryptObjectHead = notifyDecryptObject.getJSONObject("head");
        JSONObject notifyDecryptObjectBody = notifyDecryptObject.getJSONObject("requestBody");


        if ("0000".equals(notifyDecryptObjectBody.getString("bizResponseCode"))) {
            // 支付成功-走支付成功逻辑
            // 本地订单号
            String outOrderNo =  notifyDecryptObjectHead.getString("externalRefNumber");

            // 三方订单号
            String innerOrderNo = notifyDecryptObjectBody.getString("refNumber");

            // 总金额-分转元
            BigDecimal fen = new BigDecimal(notifyDecryptObjectBody.getString("amount"));
            BigDecimal amt = fen.divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);

            try {
                //处理支付逻辑
                PayOrder payOrder = payOrderService.paymentHandle(outOrderNo, innerOrderNo, amt, OrderConstant.PayMode.QUICK_PAY_BANK);
                //消费订单  支付成功发送消息
                if (!payOrder.getOrderType().equals(OrderConstant.OrderType.REFILL_ORDER)) {
                    sendOrderOrRightsOrderMsgService.paySuccessSendMsg(payOrder);
                } else {
                    //发送充值商品支付成功站内消息
                    sendPrivateMessageMsgService.send(new MessageTO(PrivateMessageConstant.MessageType.PAY_MESSAGE,
                            PrivateMessageConstant.ModelType.REFILL_PAY_SUCCESS, payOrder.getId()));
                }
            } catch (Exception e) {
                log.error("快钱快捷支付异常：" + e.getMessage());
                return result;
            }
        } else {
            // 支付失败-不进行处理,等待订单自动关闭
            log.error("快钱快捷异常回调，非下单、非退单！");
            return result;
        }
        return result;
    }



    /**
     * 快钱
     *
     * @param request 快钱回调
     * @return
     */
    @RequestMapping(value = "/quickPayNotifyUrl", method = RequestMethod.POST)
    @ResponseBody
    public JSONObject quickPayNotifyUrl(HttpServletRequest request, @RequestBody Map<String,Object> map) {
        log.info("快钱回调: {}", map);
        log.info("快钱回调: {}", request.getParameterNames());
        JSONObject result = new JSONObject();
        result.put("responseCode","00");
        result.put("responseMessage","Success");
        String txnType = (String) map.get("txnType");
        // 本地订单号
        String outOrderNo = (String) map.get("outOrderNo");
        // 三方订单号
        String innerOrderNo = (String) map.get("innerOrderNo");
        // 总金额
        Double amt = (Double) map.get("amt");
        // S 成功
        // F 失败
        String txnFlg = (String) map.get("txnFlg");
        // 支付订单
        if (QuickPayEnum.TxnType.ODR.getCode().equals(txnType)) {
            if (QuickPayEnum.TxnFlag.S.getCode().equals(txnFlg)) {
                //返回的金额
                BigDecimal money = new BigDecimal(amt);
                try {
                    //处理支付逻辑
                    PayOrder payOrder = payOrderService.paymentHandle(outOrderNo, innerOrderNo, money, OrderConstant.PayMode.QUICK_PAY);
                    //消费订单  支付成功发送消息
                    if (!payOrder.getOrderType().equals(OrderConstant.OrderType.REFILL_ORDER)) {
                        sendOrderOrRightsOrderMsgService.paySuccessSendMsg(payOrder);
                    } else {
                        //发送充值商品支付成功站内消息
                        sendPrivateMessageMsgService.send(new MessageTO(PrivateMessageConstant.MessageType.PAY_MESSAGE,
                                PrivateMessageConstant.ModelType.REFILL_PAY_SUCCESS, payOrder.getId()));
                    }
                    return result;
                } catch (RRException ex) {
                    if (ex.getCode() == OrderException.NOT_REPEAT_PAY.getCode()) {
                        return result;
                    }
                    result.put("responseCode", "01");
                    result.put("responseMessage", ex.getMsg());
                    return result;
                } catch (Exception ex) {
                    result.put("responseCode", "01");
                    result.put("responseMessage", ex.getMessage());
                    return result;
                }
            }

        } else if(QuickPayEnum.TxnType.RFD.getCode().equals(txnType)){
            // todo
            log.error("快钱退单！");
        } else {
            log.error("异常回调，非下单、非退单！");
        }

        return result;
    }
}
